package middleware

import (
	"fmt"
	"net/http"
	"runtime"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
)

// MetricsCollector 性能指标收集器
type MetricsCollector struct {
	sync.RWMutex
	RequestCount    int64
	ErrorCount      int64
	ResponseTimes   map[string][]float64
	StatusCodes     map[int]int
	ActiveGoroutine int
	HeapAlloc       uint64
	LastGC          time.Time
}

// NewMetricsCollector 创建指标收集器
func NewMetricsCollector() *MetricsCollector {
	return &MetricsCollector{
		ResponseTimes: make(map[string][]float64),
		StatusCodes:  make(map[int]int),
	}
}

// Profiler 性能分析中间件
func (mc *MetricsCollector) Profiler() gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()

		// 记录请求前的内存状态
		var m1 runtime.MemStats
		runtime.ReadMemStats(&m1)

		// 处理请求
		c.Next()

		// 更新指标
		mc.Lock()
		defer mc.Unlock()

		// 请求计数
		mc.RequestCount++

		// 响应时间
		duration := time.Since(start).Seconds() * 1000 // 转换为毫秒
		path := c.Request.URL.Path
		mc.ResponseTimes[path] = append(mc.ResponseTimes[path], duration)

		// 状态码统计
		mc.StatusCodes[c.Writer.Status()]++

		// 错误计数
		if c.Writer.Status() >= 400 {
			mc.ErrorCount++
		}

		// 更新系统指标
		var m2 runtime.MemStats
		runtime.ReadMemStats(&m2)
		mc.HeapAlloc = m2.HeapAlloc
		mc.ActiveGoroutine = runtime.NumGoroutine()
		mc.LastGC = time.Unix(0, int64(m2.LastGC))
	}
}

// GetMetrics 获取性能指标
func (mc *MetricsCollector) GetMetrics() gin.HandlerFunc {
	return func(c *gin.Context) {
		mc.RLock()
		defer mc.RUnlock()

		// 计算平均响应时间
		avgResponseTimes := make(map[string]float64)
		for path, times := range mc.ResponseTimes {
			var sum float64
			for _, t := range times {
				sum += t
			}
			avgResponseTimes[path] = sum / float64(len(times))
		}

		// 计算错误率
		errorRate := float64(mc.ErrorCount) / float64(mc.RequestCount) * 100

		metrics := gin.H{
			"timestamp":        time.Now().Format(time.RFC3339),
			"request_count":    mc.RequestCount,
			"error_count":      mc.ErrorCount,
			"error_rate":       fmt.Sprintf("%.2f%%", errorRate),
			"status_codes":     mc.StatusCodes,
			"response_times":   avgResponseTimes,
			"goroutines":       mc.ActiveGoroutine,
			"heap_alloc_mb":    float64(mc.HeapAlloc) / 1024 / 1024,
			"last_gc":          mc.LastGC.Format(time.RFC3339),
			"go_version":       runtime.Version(),
			"go_os":           runtime.GOOS,
			"go_arch":         runtime.GOARCH,
			"cpu_num":         runtime.NumCPU(),
			"goroutine_num":   runtime.NumGoroutine(),
		}

		c.JSON(http.StatusOK, metrics)
	}
}

// ResetMetrics 重置性能指标
func (mc *MetricsCollector) ResetMetrics() gin.HandlerFunc {
	return func(c *gin.Context) {
		mc.Lock()
		defer mc.Unlock()

		mc.RequestCount = 0
		mc.ErrorCount = 0
		mc.ResponseTimes = make(map[string][]float64)
		mc.StatusCodes = make(map[int]int)

		c.JSON(http.StatusOK, gin.H{"message": "Metrics reset successfully"})
	}
} 